 package com.legal.app.service.impl;

 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.legal.app.config.AvatarConfig;
 import com.legal.app.domain.User;
 import com.legal.app.domain.dto.PhoneLoginDTO;
 import com.legal.app.domain.vo.UserInfoVO;
 import com.legal.app.mapper.UserMapper;
 import com.legal.app.service.IUserService;
 import com.legal.app.common.PageParam;
 import com.legal.app.common.PageResult;
 import com.legal.common.core.domain.AjaxResult;
 import com.legal.common.core.domain.model.LoginUser;
 import com.legal.common.core.domain.entity.SysUser;
 import com.legal.common.core.redis.RedisCache;
// import com.legal.app.common.LoginUser;
 import com.legal.common.exception.GlobalException;
 import com.legal.common.exception.ServiceException;
 import com.legal.common.utils.SecurityUtils;
 import com.legal.common.utils.ShiroUtils;
 import com.legal.common.utils.StringUtils;
 import com.legal.common.utils.bean.BeanUtils;
 import com.legal.common.utils.uuid.UUID;
 import com.legal.framework.web.service.TokenService;
 import com.legal.system.domain.SysUserRole;
 import com.legal.system.mapper.SysUserMapper;
 import com.legal.system.service.ISysUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.legal.app.common.AppTokenService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.stereotype.Service;

 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.time.Duration;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;

 import com.legal.app.domain.dto.LoginResultDTO;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;

 /**
 * 小程序用户Service业务层处理
 *
 * @author Ale
 * @date 2025-05-30
 */
 @Service
 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements
 IUserService {
 @Autowired
 private UserMapper userMapper;

 /**
 * 查询小程序用户
 *
 * @param id 小程序用户主键
 * @return 小程序用户
 */
 @Override
 public User selectUserById(Long id) {
 return userMapper.selectUserById(id);
 }

 /**
 * 查询小程序用户列表
 *
 * @param user 小程序用户
 * @return 小程序用户
 */
 @Override
 public List<User> selectUserList(User user) {
 return userMapper.selectUserList(user);
 }

 /**
 * 新增小程序用户
 *
 * @param user 小程序用户
 * @return 结果
 */
 @Override
 public int insertUser(User user) {
// user.setCreateTime(DateUtils.getNowDate());
 return userMapper.insertUser(user);
 }

 /**
 * 修改小程序用户
 *
 * @param user 小程序用户
 * @return 结果
 */
 @Override
 public int updateUser(User user) {
// user.setUpdateTime(DateUtils.getNowDate());
 return userMapper.updateUser(user);
 }


 @Autowired
 private SysUserMapper sysUserMapper;
 /**
 * 批量删除小程序用户
 *
 * @param ids 需要删除的小程序用户主键和关联的系统用户主键
 * @return 结果
 */
 @Override
 @Transactional(rollbackFor = Exception.class)
 public int deleteUserByIds(Long[] ids) {
     for (Long id : ids) {
         deleteUserById(id);
         sysUserMapper.deleteUserById( id);
         userMapper.deleteUserById(id);
     }
     return 1;
 }

 /**
 * 删除小程序用户信息
 *
 * @param id 小程序用户主键
 * @return 结果
 */
 @Override
 public int deleteUserById(Long id) {
 return userMapper.deleteUserById(id);
 }

 public PageResult<User> selectUserPage(PageParam param) {
 Page<User> page = new Page<>(param.getPageNum(), param.getPageSize());
 IPage<User> iPage = userMapper.selectPage(page, null);
 return PageResult.build(iPage.getRecords(), param, iPage.getTotal());
 }

 @Autowired
 private TokenService tokenService;

 @Override
 public AjaxResult loginByPhone(PhoneLoginDTO dto) {
        // 1. 校验手机号格式
        if (!StringUtils.hasText(dto.getPhoneNumber()) ||
            dto.getPhoneNumber().length() != 11) {
            System.out.println(dto.getPhoneNumber());
            return AjaxResult.error("手机号格式不正确");
        }

        // 2. 根据手机号查询用户
        User user = userMapper.selectByPhoneNumber(dto.getPhoneNumber());
        System.out.println("用户："+user);
        if (user == null) {
            return AjaxResult.error("该手机号未注册");
        }

        // 3. 校验用户状态
        if (user.getStatus() != 1) {
            return AjaxResult.error(user.getStatus() == 0 ? "账号已注销" : "账号已冻结");
        }

        // 4. 校验密码
        String inputPassword = dto.getPassword();
//        String dbPassword = user.getEncodeCipher();
        String password = user.getEncodeCipher();
//        System.out.println("密码："+password);
        if (!new BCryptPasswordEncoder().matches(inputPassword, password))
        //先明文密码校验,后期做加密检验
//        if(!inputPassword.equals(password)){
        {
            return AjaxResult.error("密码错误");
        }


        // 5. 生成登录令牌
        LoginResultDTO result = createLoginResult(user);
         System.out.println("登录结果："+result);

        // 6. 更新最后登录时间
//        user.setUpdateTime(null);
         // 触发自动更新时间
        updateById(user);

        return AjaxResult.success(result);
    }

    /**
     * 生成登录结果
     */
    @Autowired
    private RedisCache redisCache;
    private LoginResultDTO createLoginResult(User user) {
        LoginResultDTO result = new LoginResultDTO();
        result.setUserId(user.getId());
        result.setUserType(user.getUserType());
        result.setNickName(user.getNickName());
        result.setAvatarUrl(user.getAvatarUrl());
        // 多表联查，构造SysUser和LoginUser对象
        SysUser sysUser = sysUserMapper.selectUserByUserName(user.getPhoneNumber());
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(sysUser);
        loginUser.setUserId(user.getId());
        loginUser.setUsername(user.getNickName());
        // 生成Token
        String token = tokenService.createToken(loginUser);
        loginUser.setToken(token);
        // 存入 Redis
        redisCache.setCacheObject("token:" + token, loginUser, 3600, TimeUnit.SECONDS);
        result.setToken(token);
         // 将 Duration 转换为秒和 TimeUnit.SECONDS
         Duration duration = Duration.ofHours(1);
         redisCache.setCacheObject("token:" + token, loginUser, (int) duration.getSeconds(), TimeUnit.SECONDS);
         // 存入 Redis

        result.setToken(token);
        result.setExpireTime(loginUser.getExpireTime());
        return result;
 }


  @Autowired
  private ISysUserService sysUserService;
  @Autowired
  private IUserService userService;
 @Transactional(rollbackFor = Exception.class)
 @Override
 public AjaxResult register(String phone, String password, String nickName) {
  // 1. 验证手机号是否已存在
  LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
  queryWrapper.eq(SysUser::getUserName, phone);
  SysUser list = sysUserMapper.selectUserByUserName( phone);
  // 先查出所有数据
  if (list!=null) {
   throw new RuntimeException("手机号已存在");
  }

  // 2. 创建sys_user记录
  SysUser sysUser = new SysUser();
  sysUser.setUserName(phone);
  sysUser.setNickName(nickName);
  sysUser.setPassword(new BCryptPasswordEncoder().encode(password));
  // 密码加密
//  sysUser.setUserType("00");
//  // 系统用户类型
//  sysUser.setStatus(UserStatus.NORMAL.getCode());
  // 正常状态
  sysUserService.insertUser(sysUser);

  // 3. 创建user记录
    User user = new User();
    user.setId(sysUser.getUserId());
    user.setPhoneNumber(phone);
    user.setNickName(nickName);
    user.setEncodeCipher(new BCryptPasswordEncoder().encode(password));
    user.setAvatarUrl("/images/avatar/avatar.png");
    // 默认头像
    user.setUserType(1L);
    // 普通用户
    userMapper.insert(user);
    // 4. 分配角色3）
     userMapper.insertSysUserRole(sysUser.getUserId(), 3L);

  // 小程序用户角色
    return  null;
 }

     @Override
     public UserInfoVO getCurrentUserInfo(Long userId) {
         // 获取当前登录用户ID
//         Long userId = SecurityUtils.getUserId();
         // 查询用户基础信息（从z_user表）
//         SysUser sySuser = sysUserService.selectUserById(userId);
         User user = userMapper.selectUserById(userId);
         if (user == null) {
             throw new RuntimeException("用户不存在或已注销");
         }

         // 转换为VO对象
         UserInfoVO userInfoVO = new UserInfoVO();
         BeanUtils.copyProperties(user, userInfoVO);

         // 性别数字转文字
         userInfoVO.setGenderText(String.valueOf(user.getGender()));

         // 认证状态数字转文字
         userInfoVO.setCertificationStatusText(String.valueOf(user.getCertificationStatus()));

         return userInfoVO;
     }

     /**
      * 性别数字转文字映射
      */
     private String convertGenderText(Integer gender) {
         if (gender == null) return "未知";
         Map<Integer, String> genderMap = new HashMap<>();
         genderMap.put(0, "未知");
         genderMap.put(1, "男");
         genderMap.put(2, "女");
         return genderMap.getOrDefault(gender, "未知");
     }

     /**
      * 认证状态数字转文字映射
      */
     private String convertCertificationStatusText(Integer status) {
         if (status == null) return "未认证";
         Map<Integer, String> statusMap = new HashMap<>();
         statusMap.put(0, "未认证");
         statusMap.put(1, "已认证");
         statusMap.put(2, "认证中");
         statusMap.put(3, "认证失败");
         return statusMap.getOrDefault(status, "未认证");
     }


     @Override
     @Transactional(rollbackFor = Exception.class)
     public UserInfoVO updateUserInfo(Long userId, String nickName, Integer gender, String address, String nationality, MultipartFile avatarFile) {
         // 查询用户
         User user = userMapper.selectById(userId);
         if (user == null) {
             throw new GlobalException("用户不存在");
         }

         // 更新用户信息
         user.setNickName(nickName);
         user.setGender(Long.valueOf(gender));
         user.setAddress(address);
         user.setNationality(nationality);

         // 处理头像上传
         String oldAvatarPath = user.getAvatarUrl();
         String newAvatarPath = saveAvatar(avatarFile);
         if (newAvatarPath != null) {
             user.setAvatarUrl(newAvatarPath);
             // 删除旧头像
             deleteOldAvatar(oldAvatarPath);
         }

         // 保存用户
         userMapper.updateById(user);

         // 构建返回 VO
         return convertToUserInfoVO(user);
     }

     private UserInfoVO convertToUserInfoVO(User user) {
         UserInfoVO vo = new UserInfoVO();
         vo.setId(user.getId());
         vo.setAvatarUrl(user.getAvatarUrl());
         vo.setNickName(user.getNickName());
         vo.setGender(Math.toIntExact(user.getGender()));
         vo.setGenderText(getGenderText(Math.toIntExact(user.getGender())));
         vo.setPhoneNumber(user.getPhoneNumber());
         vo.setAddress(user.getAddress());
         vo.setNationality(user.getNationality());
         vo.setCertificationStatus(Math.toIntExact(user.getCertificationStatus()));
         vo.setCertificationStatusText(getCertificationStatusText(Math.toIntExact(user.getCertificationStatus())));
         return vo;
     }
     @Autowired
     private AvatarConfig avatarConfig; // 配置类

     private String saveAvatar(MultipartFile file) {
         if (file == null || file.isEmpty()) {
             return null;
         }

         // 获取配置的上传目录
         String uploadDir = avatarConfig.getUploadDir();
         // 构造完整的物理路径（基于项目根目录）
         String projectRoot = System.getProperty("user.dir");
         String physicalPath = projectRoot + File.separator + uploadDir;

         // 生成唯一文件名
         String originalFilename = file.getOriginalFilename();
         String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
         String newFilename = UUID.randomUUID().toString() + fileExtension;

         Path uploadPath = Paths.get(physicalPath);
         if (!Files.exists(uploadPath)) {
             try {
                 Files.createDirectories(uploadPath);
             } catch (IOException e) {
                 throw new GlobalException("上传头像失败");
             }
         }

         Path destination = uploadPath.resolve(newFilename);
         try {
             Files.copy(file.getInputStream(), destination, StandardCopyOption.REPLACE_EXISTING);
         } catch (IOException e) {
             throw new GlobalException("上传头像失败");
         }

         // 返回相对路径（用于前端访问）
         return "/images/avatar/" + newFilename;
     }
     private void deleteOldAvatar(String oldAvatarPath) {
         if (oldAvatarPath == null || oldAvatarPath.isEmpty()) {
             return;
         }

         // 获取配置的上传目录
         String uploadDir = avatarConfig.getUploadDir();
         String projectRoot = System.getProperty("user.dir");
         String physicalPath = projectRoot + File.separator + uploadDir;

         // 提取文件名（如 /images/avatar/uuid.jpg → uuid.jpg）
         String filename = oldAvatarPath.replace("/images/avatar/", "");
         Path oldFilePath = Paths.get(physicalPath + filename);

         try {
             if (Files.exists(oldFilePath)) {
                 Files.delete(oldFilePath);
             }
         } catch (IOException e) {
             // 日志记录或忽略
         }
     }

     private String getGenderText(Integer gender) {
         switch (gender) {
             case 0: return "未知";
             case 1: return "男";
             case 2: return "女";
             default: return "";
         }
     }

     private String getCertificationStatusText(Integer status) {
         switch (status) {
             case 0: return "未认证";
             case 1: return "已认证";
             case 2: return "认证中";
             case 3: return "认证失败";
             default: return "";
         }
     }

     @Override
      public AjaxResult bindPhone(PhoneLoginDTO dto, String openid) {
         System.out.println(dto+"openid:"+openid);
         if (!StringUtils.hasText(dto.getPhoneNumber()) ||
                 dto.getPhoneNumber().length() != 11) {
             System.out.println(dto.getPhoneNumber());
             return AjaxResult.error("手机号格式不正确");
         }

         if(!StringUtils.hasText(dto.getPassword()))
             return AjaxResult.error("密码不能为空");
         User user = userMapper.selectUserByOpenid(openid);
         System.out.println("用户："+user);
         if(user == null) {
             return AjaxResult.error("其他异常，用户不存在");
         }
         if(user.getPhoneNumber()!=null) {
             return AjaxResult.error("手机号已绑定");
         }
         if(user.getEncodeCipher()==null){
             user.setPhoneNumber(dto.getPhoneNumber());
             user.setEncodeCipher(SecurityUtils.encryptPassword(dto.getPassword()));
            return AjaxResult.success(userMapper.updateById(user));
         }else {
             return AjaxResult.error("系统绑定手机异常");
         }
     }

     @Override
     public AjaxResult modifyPassword(Long userId, String oldPassword, String newPassword) {
         User user = userMapper.selectById(userId);
         if (new BCryptPasswordEncoder().matches(oldPassword, user.getEncodeCipher())){
             user.setEncodeCipher(SecurityUtils.encryptPassword(newPassword));
             return AjaxResult.success(userMapper.updateById(user));
         }
         return AjaxResult.error("旧密码错误");
     }

 }
